// 引入eslint插件
const eslintWebpackPlugin = require("eslint-webpack-plugin");
// 引入mini-css-extract-plugin插件
const miniPlugin = require("mini-css-extract-plugin");
// 引入html-webpack-plugin插件
const htmlPlugin = require("html-webpack-plugin");

module.exports = {
  mode: 'production',
  // 单入口打包
  // entry: "./src/app.js", // 这样打包命名默认为main
  entry: {
    app: './src/app.js' // 这样可以自定义包名为app
  },
  
  // 单入口打包，但是是将多个入口放到一块的方式
  // entry: {
  //   app: ['./src/app1.js', './src/app2.js'] // 通过数组，可以将app1和app2入口合并到一起
  // },

  // 多入口打包
  // entry: {
  //   app1: './src/app1.js',
  //   app2: './src/app2.js'
  // },
  
  output: {
    path: __dirname + '/dist',
    filename: '[name].[hash:4].bundle.js'
  },

  // 优化配置
  // optimization: {
  //   splitChunks: { // 针对多文件分割打包的策略 
  //     // 分割块的规则 all(不管同步引入还是异步引入都进行拆分)、async(异步引入才拆分)、initial(同步引入才拆分)
  //     chunks: "all",
  //     // 细致化的配置
  //     minchunks: 2, // 重复引入的次数，超过2次进行分割
  //     minSize: 1000, // 超过了1Kb左右大小才进行分割
  //     name: 'extral_pack' // 自定义分割的模块单独打包的包名
  //   }
  // },

  // 通用的优化配置，考虑到第三方库引入的情况(node_modules中包)
  optimization: {
    splitChunks: { // 针对多文件分割打包的策略 
      // 分割块的规则 all(不管同步引入还是异步引入都进行拆分)、async(异步引入才拆分)、initial(同步引入才拆分)
      chunks: "all",

      cacheGroups: {
        vender: { // 处理第三方库的分包
          test: /[\\/]node_modules[\\/]/, // 匹配node_modules路径
          filename: "vender.js", // 分包出来的名字
          chunks: "all", // 分包的规则 无论同步还是异步都分包
          minchunks: 1 // 重复次数设置为大于1则分包，因为一般第三方库，我们会在框架配置文件统一引入一次
        },
        common: { // 处理我们自己业务的重复逻辑模块分包
          filename: "common.js", // 打包的包名
          chunks: "all", // 分包的规则 无论同步还是异步都分包
          minchunks: 2, // 重复次数设置为大于2则分包
          minSize: 0 // 大于0的文件都分包，也就是所有的都分包
        }
      }
    },
    runtimeChunk: {
      name: "runtime"
    }
  },

  // loader 配置
  module: {
    rules: [
      // { // 1、字符串的loader写法，这样没法进行loader的细节配置
      //   test: /\.js$/,
      //   loader: 'babel-loader'
      // }
      { // 2、传use属性，接收数组或对象；数组用于多个loader的情况，会异常从后往前执行；对象则用于细节preset配置
        test: /\.js$/,
        use: { 
          loader: 'babel-loader',
          // 定制化loader的配置，需要通过options下的presets实现
          // 比如babel-loader的配置常用@babel/preset-env的配置，这个就是一个集成好的babel规范配置，需要进行npm安装
          // 一个loader的options的配置，可以放到根目录下对应的配置文件里面，也就可以省略options内容，
          // 比如我们这里的options可以放到根目录下的.babelrc文件中，并以JSON的格式编写
          // options: {
          //   presets: [ // 支持多个preset配置
          //     [
          //       '@babel/preset-env', // preset包名
          //       { // preset规范内容编写，之后转换的语法就是适配我们写的配置了
          //         targets: {
          //           browsers: [
          //             ">1%", // 支持所有占有率大于1%的游览器
          //             "last 2 version", // 支持游览器的最后两个版本
          //             "not ie<=8" // 不支持小于等于IE8的游览器
          //           ]
          //         },
          //         // ...
          //       }
          //     ]
          //   ]
          // }
        }
      },

      // style-loader 处理方案
      // 先执行css-loader帮助webpack识别css，之后使用style-loader告诉webpack如何处理css，也就是放到style标签中
      // {
      //   test: /\.css$/,
      //   use: ['style-loader', 'css-loader']
      // },

      // mini-css-extract-plugin 处理css方案
      // 该插件不仅提供了插件，还提供了一个loader，两个都需要进行引入使用；之后对于css文件会单独打包出来
      {
        test: /\.css$/,
        use: [miniPlugin.loader, 'css-loader']
      },
      // 如果使用了css预处理语言，比如less，那么我们需要安装less、less-loader；sass预处理同理
      // less-loader先提供webpack识别less文件和处理less样式为css样式，之后按照正常的css样式loader处理方案走即可
      {
        test: /\.less$/,
        use: [miniPlugin.loader, 'css-loader', 'less-loader']
      },

      // url-loader（推荐）方案处理图片资源
      // file-laoder主要适用webpack3/4，且功能比较普通，单纯为了webpack识别资源的一个loader
      // 因此，这里使用url-loader（推荐）进行操作，但是file-loader也需要安装，因为url-loader依赖于file-loader
      // 如果处理视频资源，或字体资源，只需要修改test即可，配置一样
      // {
      //   test: /\.(jpg|jpeg|png|gif|svg)$/,
      //   loader: 'url-loader',
      //   options: { // url-laoder提供了options选项
      //     limit: 5000, // 小于20kb左右的才进行base转换
      //     name: "[name].[hash].[ext]" // 没有被转换的资源文件则单独拿出来并重命名
      //   }
      // },

      // webpack5 自带资源处理的方案
      // 这里配置等同于上面的配置
      {
        test: /\.(jpg|jpeg|png|gif|svg)$/,
        // webpack5 提供type来处理资源，参数常用asset(结合parser和generator进行分类操作) | asset/inline(全部转码) | asset/resource(全部都不转码)
        type: 'asset',
        parser: {
          dataUrlCondition: { 
            maxSize: 5000 // 等同于url-loader的limit
          }
        },
        generator: { 
          filename: "[name].[hash].[ext]" // 等同于url-loader的name
        }
      }
    ]
  },

  // plugin 配置
  plugins: [
    // 使用插件，在plugins数组中new对应的插件即可，插件的配置作为参数传入即可
    // 但是，如果配置写在参数里面，会导致webpack.config.js代码过多，不美观；可以放到根目录下的配置文件，
    // 比如这里可以放到根目录下的.eslintrc.js中，eslint配置文件支持模块化的js文件编写
    new eslintWebpackPlugin({}),

    // mini-css-extract-plugin 处理css方案
    new miniPlugin({}),

    // html-webpack-plugin 
    // 单页面打包
    new htmlPlugin({
      template: './index.html', // 提供构建的html的模版，这里直接映射某个文件
      filename: 'index.html', // 自定义打包出来的html文件名称
      chunks: ["app"], // 区分需要引入哪个JS出口模块
      minify: { // 对打包的HTML文件规范作要求，默认是压缩且优化的
        collapseWhitespace: true, // 打包的HTMl是否进行去空格压缩
        removeComments: true, // 打包的HTML是否允许注释
        removeAttributeQuotes: true // 打包的HTML是否允许移除没有意义的空格，比如函数括号间的空格等
      },
      inject: "body", // JS模块引入到HTML中什么位置，默认在head里面；可选 body|true(body和true功能意义)、head、false(不引入JS)
      title: "webpack demo"
    }),

    // 如果是多页面的打包，我们需要多次使用htmlPlugin，比如我们这里有两个页面出口，就需要配置两次，且使用chunks来区别页面名称
    // new htmlPlugin({
    //   template: './index.html', // 提供构建的html的模版，这里直接映射某个文件
    //   filename: 'index1.html', // 自定义打包出来的html文件名称
    //   chunks: ["app1"], // 区分需要引入哪个JS出口模块
    //   minify: { // 对打包的HTML文件规范作要求，默认是压缩且优化的
    //     collapseWhitespace: true, // 打包的HTMl是否进行去空格压缩
    //     removeComments: true, // 打包的HTML是否允许注释
    //     removeAttributeQuotes: true // 打包的HTML是否允许移除没有意义的空格，比如函数括号间的空格等
    //   },
    // }),
    // new htmlPlugin({
    //   template: './index.html', // 提供构建的html的模版，这里直接映射某个文件
    //   filename: 'index2.html', // 自定义打包出来的html文件名称
    //   chunks: ["app2"] // 区分需要引入哪个JS出口模块 
    // }),
    
  ]
}